<template>
  <div
    class="svg_box"
    :style="{
      width: `${sideLen}px`,
      height: `${sideLen}px`,
    }"
  >
    <svg
      xmlns="http://www.w3.org/2000/svg"
      class="circle_box"
      x="0px"
      y="0px"
      :width="sideLen"
      :height="sideLen"
      :viewBox="`0 0 ${sideLen} ${sideLen}`"
    >
      <circle
        class="bg_circle"
        :cx="singleSideLen"
        :cy="singleSideLen"
        :r="r"
        :stroke="stroke"
        fill="none"
        :stroke-width="strokeWidth"
      />
      <path
        class="svg_circle"
        :class="circleKid"
        :d="`M ${singleSideLen}, ${singleSideLen}
        m ${r}, 0
        a${r},${r} 0 1,1 -${2 * r},0
        a${r},${r} 0 1,1 ${2 * r},0`"
        :stroke="stroke"
        fill="none"
        :stroke-width="strokeWidth"
      />
    </svg>
    <span
      :class="countKid"
      class="count"
      :style="{
        color: countColor,
      }"
      >0</span
    >
  </div>
</template>
<script lang="ts">
let key = 1;
</script>

<script lang="ts" setup>
import { toRefs, nextTick } from 'vue';
import anime from 'animejs';
import type { SocialAnl } from '@/types/animejsType';

export interface CircleProps {
  r?: number;
  strokeWidth?: number;
  stroke?: string;
  rate?: number;
  countColor?: string;
  totalScore?: number;
  delay?: number;
  duration?: number;
  [k: string]: any;
}
// 设置动画的唯一class
const countKid = `count_${key++}`;
const circleKid = `circle_${key++}`;

const props = withDefaults(defineProps<CircleProps>(), {
  r: 50,
  strokeWidth: 5,
  stroke: '#df6c4f',
  rate: 100.0,
  totalScore: 100,
  countColor: '#fff',
  delay: 0,
  duration: 1000,
});

const {
  r,
  strokeWidth,
  stroke,
  rate,
  countColor,
  totalScore,
  delay,
  duration,
} = toRefs(props);
const sideLen = r.value * 2 + strokeWidth.value * 2;
const singleSideLen = r.value + strokeWidth.value;
// 环形绘制长度
const strokeDashW =
  2 * Math.PI * r.value * ((totalScore.value - rate.value) / totalScore.value);

let countAni: SocialAnl, circleAni: SocialAnl;
nextTick(() => {
  countAni = anime({
    targets: `.${countKid}`,
    innerHTML: [0, rate.value],
    easing: 'cubicBezier(.6, .2, .1, .6)',
    duration: duration.value,
    delay: delay.value,
    round: 100,
  });
  circleAni = anime({
    targets: `.circle_box .${circleKid}`,
    strokeDashoffset: [anime.setDashoffset, strokeDashW],
    easing: 'cubicBezier(.6, .2, .1, .6)',
    duration: duration.value,
    delay: delay.value,
    direction: 'alternate',
    loop: false,
  });
});
// 重启动画
const restart = () => {
  countAni && countAni.restart();
  circleAni && circleAni.restart();
};
// 将重启动画暴露出去
defineExpose({
  restart,
});
// #df6c4f
</script>

<style lang="scss" scoped>
.svg_box {
  position: relative;
  .circle_box {
    position: relative;
    transform: rotate(-90deg);
    transform-origin: 50% 50%;
  }
  .bg_circle {
    opacity: 0.4;
  }
  .count {
    position: absolute;
    top: 50%;
    left: 50%;
    transform: translate(-50%, -50%);
    font-size: 18px;
  }
}
</style>
